package com.ai.platform.core.interceptor;

import com.ai.platform.common.util.AiPlatformUtil;
import com.ai.platform.common.util.ConvertUtil;
import com.ai.platform.core.annotation.InvokeService;
import com.ai.platform.core.context.InvocationContextHolder;
import com.ai.platform.model.dto.Input;
import com.alibaba.fastjson.JSON;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by yeyingsheng on 2018/5/13.
 * 核心拦截器
 */
public abstract class AICoreInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(AICoreInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        InvocationContextHolder.setContext(request.getServletContext(),request,response);
        //设置参数
        if(handler instanceof HandlerMethod){
            logger.debug("参数设置");
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            InvokeService invokeService=handlerMethod.getMethodAnnotation(InvokeService.class);
            InvocationContextHolder contextHolder=InvocationContextHolder.getContext();
            Input input=contextHolder.getInput();
            input.setIp(request.getRemoteHost());
            if(null!=invokeService) {
                input.setServiceName(invokeService.serviceName());
                input.setMethod(invokeService.method());
            }
            Map<String, String[]> parameterMap;
            if(request instanceof MultipartHttpServletRequest){
                //文件
                MultipartHttpServletRequest multipartHttpServletRequest= (MultipartHttpServletRequest) request;
                MultiValueMap<String, MultipartFile> multiValueMap= multipartHttpServletRequest.getMultiFileMap();
                if(!CollectionUtils.isEmpty(multiValueMap)) {
                    for (Map.Entry<String, List<MultipartFile>> entry : multiValueMap.entrySet()) {
                        Map<String,String[]> map=new HashMap<>();
                        String key = entry.getKey();
                        List<MultipartFile> multipartFileList = entry.getValue();
                        String[] values=new String[multipartFileList.size()];
                        if(!CollectionUtils.isEmpty(multipartFileList)) {
                            for (int i=0;i<multipartFileList.size();i++){
                                MultipartFile multipartFile=multipartFileList.get(i);
                                if (!multipartFile.isEmpty()) {
                                    values[i]=ConvertUtil.inputStreamToString(multipartFile.getInputStream());
                                }
                            }
                        }
                        map.put(key,values);
                        input.addInputMap(map);
                    }
                }
                parameterMap=multipartHttpServletRequest.getParameterMap();
            }else {
                parameterMap = request.getParameterMap();
            }
            if(!CollectionUtils.isEmpty(parameterMap)){
                for (Map.Entry<String, String[]> entry:parameterMap.entrySet()){
                    Map<String,String[]> map=new HashMap<>();
                    String key=entry.getKey();
                    String[] values=entry.getValue();
                    map.put(key,values);
                    input.addInputMap(map);
                }
            }
            Subject subject;
            try {
                subject = SecurityUtils.getSubject();
            }catch (Exception e){
                subject=null;
            }
            if(null!=subject && subject.isAuthenticated()){
                String obj = Base64Utils.encodeToString(JSON.toJSONString(subject.getPrincipal()).getBytes());

                contextHolder.getInput().putValue(AiPlatformUtil.MD5(AiPlatformUtil.PLATFORM_SESSION_USER_SUBJECT), obj);
            }
        }
        boolean isPreHandle=false;
        try {
            isPreHandle = preHandle(handler);
        }catch (Exception e){
            logger.error("preHandle调用异常：{}",e.getMessage());
            e.printStackTrace();
        }finally {
            if(!isPreHandle){
                logger.debug("InvocationContextHolder对象清理");
                InvocationContextHolder.clearContext();
            }
        }
        return isPreHandle;
    }

    public abstract boolean preHandle(Object handler) throws Exception ;


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        postHandle(handler,modelAndView);
    }

    public abstract void postHandle( Object handler, ModelAndView modelAndView) throws Exception;


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        try {
            afterCompletion(handler, ex);
        }catch (Exception e){
            logger.error("afterCompletion执行异常：{}",e.getMessage());
            e.printStackTrace();
        }finally {
            //清理InvocationContextHolder对象
            logger.debug("InvocationContextHolder对象清理");
            InvocationContextHolder.clearContext();
        }
    }

    public abstract void afterCompletion(Object handler, Exception ex) throws Exception;

}
